﻿using LingYue_PictureProcessCenter.Core.HardwareInfo;
using LingYue_PictureProcessCenter.Core.PictureInfo;
using LingYue_PictureProcessCenter.Core.ProcessInfo;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;

namespace LingYue_PictureProcessCenter.Panel
{
    /// <summary>
    /// RealESRGAN.xaml 的交互逻辑
    /// </summary>
    public delegate void DelReadStdOutput(string result);

    public delegate void DelReadErrOutput(string result);

    public partial class RealESRGAN : UserControl, IConfigPanel
    {
        public event DelReadStdOutput ReadStdOutput;

        public event DelReadErrOutput ReadErrOutput;

        private RealEsrPictureInfoImpl PictureInfo { get; set; }
        private RealEsrProcessInfoImpl ProcessInfo { get; set; }
        public Process CmdProcess { get; set; }
        public bool IsRunning { get; set; }
        private string LogCache = "";

        public RealESRGAN(BasePictureInfoImpl PInfo, HardwareInfo HInfo)
        {
            PictureInfo = new RealEsrPictureInfoImpl(PInfo);
            ProcessInfo = new RealEsrProcessInfoImpl(PictureInfo);
            ProcessInfo.HardwareInfo = HInfo;
            InitializeComponent();

            GPUSelect.Items.Add("Auto Select");
            foreach (Dictionary<string, string> Dic in HInfo.HardwareInfoList)
            {
                GPUSelect.Items.Add(Dic["Description"]);
            }
            GPUSelect.SelectedIndex = 0;
            IsRunning = false;
        }

        private void StartProcessButton_Click(object sender, RoutedEventArgs e)
        {
            PictureInfo.TTLMode = (bool)UseTTLModeCheckBox.IsChecked!;
            if (GPUSelect.SelectedIndex == 0)
                PictureInfo.GPUID = "auto";
            else
                PictureInfo.GPUID = (GPUSelect.SelectedIndex - 1).ToString();
            PictureInfo.Format = OutputFormatSelect.Text;
            PictureInfo.Scale = int.Parse(ScaleSelect.Text);
            PictureInfo.SelectModel = ModelSelect.Text;
            PictureInfo.InputPath = ((MainWindow)Application.Current.MainWindow).InputPathTextBox.Text;
            PictureInfo.OutputPath = ((MainWindow)Application.Current.MainWindow).OutputPathTextBox.Text;
            if (PictureInfo.InputPath == "")
            {
                MessageBox.Show("缺失输入文件路径");
                return;
            }
            if (PictureInfo.OutputPath == "")
            {
                MessageBox.Show("缺失输出文件路径");
                return;
            }
            if (PictureInfo.GPUID == "-1")
            {
                MessageBox.Show("未指定执行GPU");
                return;
            }
            EndProcessButton.IsEnabled = true;
            LogTextBlock.Text = "";
            LogCache = "";
            LogTextBlock.Text += ProcessInfo.GenerateCommand();

            ReadErrOutput = new DelReadErrOutput(ReadErrOutputAction);
            ReadStdOutput = new DelReadStdOutput(ReadStdOutputAction);

            CmdProcess = new Process();
            CmdProcess.StartInfo.FileName = ProcessInfo.ExecuteFilePath;
            CmdProcess.StartInfo.Arguments = ProcessInfo.PictureInfo.GetCommandString();

            CmdProcess.StartInfo.CreateNoWindow = true;
            CmdProcess.StartInfo.UseShellExecute = false;
            CmdProcess.StartInfo.RedirectStandardError = true;
            CmdProcess.StartInfo.RedirectStandardOutput = true;
            CmdProcess.StartInfo.RedirectStandardInput = true;

            CmdProcess.OutputDataReceived += new DataReceivedEventHandler(_OutputDataReceived);
            CmdProcess.ErrorDataReceived += new DataReceivedEventHandler(_ErrorDataReceived);

            CmdProcess.EnableRaisingEvents = true;
            CmdProcess.Exited += new EventHandler(CmdProcess_Exited);

            CmdProcess.Start();
            CmdProcess.BeginOutputReadLine();
            CmdProcess.BeginErrorReadLine();
            IsRunning = true;
        }

        private void _OutputDataReceived(object sender, DataReceivedEventArgs e)
        {
            if (e.Data != null)
            {
                this.Dispatcher.Invoke(ReadStdOutput, new object[] { e.Data });
            }
        }

        private void _ErrorDataReceived(object sender, DataReceivedEventArgs e)
        {
            if (e.Data != null)
            {
                this.Dispatcher.Invoke(ReadErrOutput, new object[] { e.Data });
            }
        }

        private void ReadStdOutputAction(string result)
        {
            this.LogTextBlock.Text += (result + "\r\n");
            LogCache += (result + "\r\n");
            LogTextScroll.ScrollToBottom();
        }

        private void ReadErrOutputAction(string result)
        {
            this.LogTextBlock.Text += (result + "\r\n");
            LogCache += (result + "\r\n");
            LogTextScroll.ScrollToBottom();
        }

        private void CmdProcess_Exited(object sender, EventArgs e)
        {
            // 检查是否执行成功
            string[] LogOutWord = LogCache.Split(" ");
            this.Dispatcher.Invoke(new Action(
                delegate
                {
                    if (CmdProcess.ExitCode == 0)
                    {
                        string OutputFullPath = String.Format(
                                "{0}\\{1}_output.{2}",
                                PictureInfo.OutputPath,
                                System.IO.Path.GetFileNameWithoutExtension(PictureInfo.InputPath),
                                PictureInfo.Format);
                        LogTextBlock.Text += "\r\n----------------\r\n";
                        LogTextBlock.Text += OutputFullPath + "\r\n";
                        LogTextBlock.Text += "目录已放入剪贴板";
                        Clipboard.SetText(OutputFullPath);
                    }
                    else if (CmdProcess.ExitCode == -1)
                    {
                        LogTextBlock.Text += "\r\n----------------\r\n";
                        LogTextBlock.Text += "程序已经终止";
                    }
                    else
                    {
                        LogTextBlock.Text += "\r\n----------------\r\n";
                        LogTextBlock.Text += "程序异常，退出代码" + CmdProcess.ExitCode;
                    }
                    EndProcessButton.IsEnabled = false;
                }
            ));
            IsRunning = false;
        }

        private void EndProcessButton_Click(object sender, RoutedEventArgs e)
        {
            if (!CmdProcess.HasExited)
            {
                CmdProcess.Kill();
            }
        }
    }
}